import threading
import time
import inspect
from functools import wraps
from typing import Callable, Type, Dict, Any, List
from simplehtf.core.phase import PhaseResult


class BasePlug:
    def setup(self):
        pass

    def teardown(self):
        pass


def plug(**plug_classes: Type['BasePlug']):
    def decorator(func):
        @wraps(func)
        def wrapper(*wrapper_args, **wrapper_kwargs):
            plug_instances = {name: cls() for name, cls in plug_classes.items()}

            for p in plug_instances.values():
                p.setup()

            sig = inspect.signature(func)

            try:
                bound = sig.bind_partial(*wrapper_args, **wrapper_kwargs)
            except TypeError:
                bound = inspect.BoundArguments(sig, {})

            for name, instance in plug_instances.items():
                if name in sig.parameters and name not in bound.arguments:
                    bound.arguments[name] = instance
            try:
                bound.apply_defaults()
            except Exception:
                pass

            try:
                result = func(**bound.arguments)
            except Exception as e:
                print(f"[ERROR] Phase {func.__name__} failed: {e}")
                result = PhaseResult.ERROR
            finally:
                for p in plug_instances.values():
                    try:
                        p.teardown()
                    except Exception as e:
                        print(f"[ERROR] teardown failed for {p}: {e}")

            return result or PhaseResult.CONTINUE

        return wrapper
    return decorator
